﻿// Copyright � 2017-2020 Chromely Projects. All rights reserved.
// Use of this source code is governed by MIT license that can be found in the LICENSE file.

namespace Chromely.Loader;

/// <summary>
/// Creates CEF binaries download notification messages in html pages and launches the html pages to notify users.
/// </summary>
public class HtmlCefDownloadNotification : ICefDownloadNotification
{
    /// <summary>
    /// The Chromely logo base6encoded.
    /// </summary>
    private const string ChromelyImgBase6Encoded = "";

    private IList<string> FileList;

    /// <summary>
    /// Initializes a new instance of <see cref="HtmlCefDownloadNotification"/>.
    /// </summary>
    public HtmlCefDownloadNotification()
    {
        FileList = new List<string>();
    }

    /// <summary>
    /// Shows html page to notify the user that the download has started.
    /// </summary>
    public virtual void OnDownloadStarted()
    {
        var message = new Tuple<string, string, string>(
            "CEF binaries download started.",
            "Note that depending on your network, this might take up to 4 minutes to complete.",
            "Please wait...");

        var tempFile =  ShowPageWithCustomMessage(message);
        FileList.Add(tempFile);
    }

    /// <summary>
    /// Shows html page to notify the user that the download was completed.
    /// </summary>
    /// <param name="duration">The duration info.</param>
    public virtual void OnDownloadCompleted(TimeSpan duration)
    {
        var message = new Tuple<string, string, string>(
            "CEF binaries download completed successfully.",
            $"Time elapsed: {duration}.",
            "Please close.");

        var tempFile = ShowPageWithCustomMessage(message);
        FileList.Add(tempFile);
    }


    /// <summary>
    /// Shows html page to notify the user that the download has failed.
    /// </summary>
    /// <param name="exception">The exception on failure.</param>
    public virtual void OnDownloadFailed(Exception exception)
    {
        var message = new Tuple<string, string, string>(
            "CEF binaries download completed with error.",
            "Error message: " + exception.Message,
            "Please close.");

        var tempFile = ShowPageWithCustomMessage(message);
        FileList.Add(tempFile);
    }

    public virtual void Cleanup()
    {
        if (FileList is null || !FileList.Any())
        {
            return;
        }

        foreach (var file in FileList)
        {
            try
            {
                File.Delete(file);
            }
            catch (Exception ex)
            {
                Logger.Instance.Log.LogError(ex);
                throw;
            }
        }
    }

    /// <summary>
    /// Shows a page to notify the user.
    /// </summary>
    /// <param name="message">
    /// The message.
    /// </param>
    /// <returns>
    /// The temporary file created.
    /// </returns>
    private static string ShowPageWithCustomMessage(Tuple<string, string, string> message)
    {
        try
        {
            var xDocument = new XDocument(
                new XDocumentType("html", null, null, null),
                new XElement(
                    "html",
                                new XAttribute("lang", "en"),
                                new XElement(
                                    "head",
                                    new XElement(
                                        "meta",
                                        new XAttribute("http-equiv", "content-type"),
                                        new XAttribute("content", "text/html"),
                                        new XAttribute("charset", "utf-8")),
                                    new XElement("title", "Chromely CEF Binaries Download"),
                                    new XElement(
                                        "style",
                                        new XAttribute("type", "text/css"),
                                        "#box_1 { position: absolute; top: 75px; right: 75px; bottom: 75px; left: 75px; } #box_2 { position: absolute; top:150px; right: 150px; bottom: 150px; left: 150px; }")),
                                new XElement(
                                    "body",
                                    new XElement("div", new XAttribute("id", "box_1")),
                                    new XElement(
                                        "div",
                                        new XAttribute("id", "box_2"),
                                        new XAttribute("align", "center")),
                                    new XElement(
                                        "img",
                                        new XAttribute("src", ChromelyImgBase6Encoded)),
                                    new XElement("h1", "chromely"),
                                    new XElement("div", message.Item1),
                                    new XElement("div", message.Item2),
                                    new XElement("div", message.Item3),
                                    new XElement("p", string.Empty),
                                    new XElement("div", "For more info - ", new XElement("a", "Chromely Apps", new XAttribute("href", "https://github.com/chromelyapps/Chromely"))),
                                    new XElement("p", string.Empty),
                                    new XElement(
                                        "input",
                                        new XAttribute("type", "button"),
                                        new XAttribute("value", "Close"),
                                        new XAttribute("onclick", "window.close()")))));

            var settings = new XmlWriterSettings
            {
                OmitXmlDeclaration = true,
                Indent = true,
                IndentChars = "\t"
            };

            var htmlFileName = Guid.NewGuid() + ".html";

            using (var writer = XmlWriter.Create(htmlFileName, settings))
            {
                xDocument.WriteTo(writer);
            }

            if (CefRuntime.Platform == CefRuntimePlatform.Linux)
            {
                Process.Start("xdg-open", htmlFileName);
            }
            else if (CefRuntime.Platform == CefRuntimePlatform.MacOS)
            {
                Process.Start("open", htmlFileName);
            }
            else
            {
                try
                {
                    Process.Start(htmlFileName);
                }
                catch
                {
                    try
                    {
                        Process.Start(@"cmd.exe ", @"/c " + htmlFileName);
                    }
                    catch
                    {
                        // ignored
                    }
                }
            }

            return htmlFileName;
        }
        catch (Exception e)
        {
            Logger.Instance.Log.LogError(e);
            Console.WriteLine(message);
        }

        return string.Empty;
    }
}